import fs from 'fs';
import path from 'path';
import { execSync } from 'child_process';

// 读取 .env
const env = fs.readFileSync('.env', 'utf8');
const apiKey = env.match(/DASHSCOPE_API_KEY\s*=\s*(.+)/)?.[1]?.trim();
if (!apiKey) throw new Error('请先在 .env 中写入 DASHSCOPE_API_KEY');

// 创建输出目录
const outDir = 'output';
fs.existsSync(outDir) || fs.mkdirSync(outDir);

// ---------- 1. 文生视频 ----------
async function genVideo() {
  const story = fs.readFileSync('input.txt', 'utf8').trim();
  
  // 将故事分解为多个片段
  const segments = splitStoryIntoSegments(story);
  console.log(`将故事分割为 ${segments.length} 个片段进行视频生成`);
  
  const videoUrls = [];
  
  // 为每个片段生成视频
  for (let i = 0; i < segments.length; i++) {
    const prompt = segments[i];
    const body = {
      model: 'wan2.2-t2v-plus',
      input: { prompt },
      parameters: { size: '1920*1080' },
    };

    console.log(`正在生成第 ${i+1}/${segments.length} 个视频片段: ${prompt.substring(0, 50)}...`);

    // 1.1 提交任务
    let r = await fetch('https://dashscope.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${apiKey}`,
        'Content-Type': 'application/json',
        'X-DashScope-Async': 'enable'
      },
      body: JSON.stringify(body),
    });
    
    const responseText = await r.text();
    let responseJson;
    try {
      responseJson = JSON.parse(responseText);
    } catch (e) {
      throw new Error(`API返回非JSON响应: ${responseText}`);
    }
    
    if (!r.ok) {
      // 特殊处理欠费情况
      if (responseJson && responseJson.code === "Arrearage") {
        throw new Error(`账户余额不足或欠费，请前往阿里云百炼平台充值后再试: ${responseJson.message}`);
      }
      
      throw new Error(`API调用失败，状态码: ${r.status}，响应: ${responseText}`);
    }
    
    if (!responseJson.output) {
      throw new Error(`API响应缺少output字段: ${responseText}`);
    }
    
    if (!responseJson.output.task_id) {
      throw new Error(`API响应缺少task_id字段: ${responseText}`);
    }
    
    const { output: { task_id } } = responseJson;

    // 1.2 轮询
    console.log(`第${i+1}个视频任务已提交，task_id =`, task_id);
    let status, url;
    while (true) {
      await new Promise(res => setTimeout(res, 5000));
      r = await fetch(`https://dashscope.aliyuncs.com/api/v1/tasks/${task_id}`, {
          headers: { Authorization: `Bearer ${apiKey}` },
        });
      
      const data = await r.json();
      status = data.output.task_status;
      if (status === 'SUCCEEDED') {
        url = data.output.video_url;
        videoUrls.push(url);
        break;
      }
      if (status === 'FAILED') {
        throw new Error(`视频生成失败: ${JSON.stringify(data)}`);
      }
      console.log(`等待第${i+1}个视频生成... 当前状态`, status);
    }
    
    // 1.3 下载每个视频片段
    const res = await fetch(url);
    const buffer = await res.arrayBuffer();
    const filename = `raw_${i}.mp4`;
    fs.writeFileSync(path.join(outDir, filename), Buffer.from(buffer));
    console.log(`✅ 第${i+1}个视频已保存 ${filename}`);
  }
  
  // 1.4 拼接视频
  console.log('开始拼接视频片段...');
  mergeVideoSegments(segments.length);
  
  return videoUrls.length;
}

// 将故事分割成片段的函数
function splitStoryIntoSegments(story) {
  // 移除多余的空白字符
  story = story.replace(/\s+/g, ' ').trim();
  
  // 估算每个片段的字符数 (中文约每秒3-5个字)
  const CHARS_PER_SEGMENT = 25; 
  const segments = [];
  
  // 按句号分割故事
  let sentences = story.split(/(?<=[。！？.!?])/);
  
  let currentSegment = '';
  for (let sentence of sentences) {
    // 如果加上这个句子会超过限制，就保存当前段落
    if (currentSegment.length + sentence.length > CHARS_PER_SEGMENT && currentSegment.length > 0) {
      segments.push(currentSegment.trim());
      currentSegment = sentence;
    } else {
      currentSegment += sentence;
    }
  }
  
  // 添加最后一个段落
  if (currentSegment.trim().length > 0) {
    segments.push(currentSegment.trim());
  }
  
  // 如果分割后的段落太少(少于2个)，则按字符数强制分割
  if (segments.length < 2) {
    segments.length = 0; // 清空
    for (let i = 0; i < story.length; i += CHARS_PER_SEGMENT) {
      segments.push(story.substring(i, Math.min(i + CHARS_PER_SEGMENT, story.length)));
    }
  }
  
  return segments;
}

// 拼接视频片段
function mergeVideoSegments(segmentCount) {
  // 创建一个临时文件列表
  let fileList = '';
  for (let i = 0; i < segmentCount; i++) {
    fileList += `file '${path.join(outDir, `raw_${i}.mp4`).replace(/\\/g, '/')}'\n`;
  }
  fs.writeFileSync(path.join(outDir, 'filelist.txt'), fileList);
  
  // 使用FFmpeg拼接视频
  try {
    execSync(
      `ffmpeg -y -f concat -safe 0 -i ${outDir}/filelist.txt -c copy ${outDir}/raw.mp4`,
      { stdio: 'inherit' }
    );
    console.log('✅ 视频片段已拼接为完整视频 raw.mp4');
  } catch (error) {
    console.error('❌ 视频拼接失败，请确认已安装FFmpeg并添加到系统PATH中');
    throw error;
  }
}

// ---------- 2. 文生语音 ----------
async function genAudio() {
  try {
    // 读取输入文本
    const text = fs.readFileSync('input.txt', 'utf8').trim();
    if (!text) throw new Error('请先在 input.txt 中输入文本内容');

    // 调用阿里云百炼平台的TTS服务
    const body = {
      model: 'qwen-tts',
      input: {
        text: text,
        voice: 'Cherry'
      }
    };

    const response = await fetch('https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(body)
    });

    const responseText = await response.text();
    let responseJson;
    try {
      responseJson = JSON.parse(responseText);
    } catch (e) {
      throw new Error(`API返回非JSON响应: ${responseText}`);
    }

    if (!response.ok) {
      // 检查是否是内容审核失败
      if (responseJson && responseJson.code === "DataInspectionFailed") {
        console.warn('⚠️ 语音生成失败: 输入内容未通过安全审核');
        console.warn('详细信息:', responseJson.message);
      } else if (responseJson && responseJson.code === "Arrearage") {
        console.warn('⚠️ 语音生成失败: 账户余额不足或欠费，请前往阿里云百炼平台充值后再试');
        console.warn('详细信息:', responseJson.message);
      } else {
        console.warn('⚠️ 语音生成失败: API调用失败，状态码:', response.status, '，响应:', responseText);
      }
      console.log('将使用现有的语音文件（如果存在）');
      return false;
    }

    if (!responseJson.output || !responseJson.output.audio || !responseJson.output.audio.url) {
      throw new Error(`API响应缺少音频URL: ${responseText}`);
    }

    // 下载音频文件
    const audioUrl = responseJson.output.audio.url;
    const audioRes = await fetch(audioUrl);
    const audioBuffer = await audioRes.arrayBuffer();
    fs.writeFileSync(path.join(outDir, 'voice.mp3'), Buffer.from(audioBuffer));
    console.log('✅ 语音已保存 voice.mp3');
    return true;
  } catch (error) {
    console.warn('⚠️ 语音生成失败:', error.message);
    console.log('将使用现有的语音文件（如果存在）');
    return false;
  }
}

// ---------- 3. 生成字幕 ----------
function genSubtitle() {
  try {
    // 读取输入文本
    const text = fs.readFileSync('input.txt', 'utf8').trim();
    if (!text) throw new Error('请先在 input.txt 中输入文本内容');

    // 创建简单的SRT字幕文件
    const srtContent = `1
00:00:00,000 --> 00:00:05,000
${text}
`;
    
    const subtitlePath = path.join(outDir, 'subtitle.srt');
    fs.writeFileSync(subtitlePath, srtContent, 'utf8');
    console.log('✅ 字幕已保存 subtitle.srt');
    return true;
  } catch (error) {
    console.warn('⚠️ 字幕生成失败:', error.message);
    return false;
  }
}

// ---------- 4. 合成 ----------
function merge() {
  const rawVideoPath = path.join(outDir, 'raw.mp4');
  const voicePath = path.join(outDir, 'voice.mp3');
  const subtitlePath = path.join(outDir, 'subtitle.srt');
  const finalPath = path.join(outDir, 'final.mp4');

  // 检查输入文件是否存在
  if (!fs.existsSync(rawVideoPath)) {
    throw new Error(`视频文件不存在: ${rawVideoPath}`);
  }
  if (!fs.existsSync(voicePath)) {
    throw new Error(`音频文件不存在: ${voicePath}`);
  }

  try {
    // 检查字幕文件是否存在
    if (fs.existsSync(subtitlePath)) {
      // 如果字幕文件存在，则在合成时添加字幕
      execSync(
        `ffmpeg -y -i ${outDir}/raw.mp4 -i ${outDir}/voice.mp3 -vf "subtitles=${outDir}/subtitle.srt" -c:v libx264 -c:a aac -shortest -movflags +faststart -g 15 -force_key_frames "expr:gte(t,n_forced*15)" ${outDir}/final.mp4`,
        { stdio: 'inherit' }
      );
    } else {
      // 如果没有字幕文件，则按原方式合成
      execSync(
        `ffmpeg -y -i ${outDir}/raw.mp4 -i ${outDir}/voice.mp3 -c:v libx264 -c:a aac -shortest -vf "fade=in:0:15,fade=out:225:15" -movflags +faststart -g 15 -force_key_frames "expr:gte(t,n_forced*15)" ${outDir}/final.mp4`,
        { stdio: 'inherit' }
      );
    }
  } catch (error) {
    console.error('FFmpeg执行失败，请确认已安装FFmpeg并添加到系统PATH中');
    throw error;
  }
}

// ---------- 主流程 ----------
async function main() {
  try {
    console.log('开始生成视频...');
    await genVideo();
    const audioSuccess = await genAudio();
    // 生成字幕
    genSubtitle();
    // 如果语音生成成功或者存在语音文件，则进行合成
    const voicePath = path.join(outDir, 'voice.mp3');
    if (audioSuccess || fs.existsSync(voicePath)) {
      console.log('开始合成视频和音频...');
      merge();
      console.log('🎉 成片已输出：output/final.mp4');
    } else {
      console.log('⚠️ 由于缺少音频文件，跳过视频合成');
    }
  } catch (error) {
    console.error('生成过程出错:', error.message);
    if (error.message.includes('Arrearage')) {
      console.log('\n💡 解决方案:');
      console.log('1. 登录阿里云百炼平台 (https://help.aliyun.com/zh/model-studio/)');
      console.log('2. 检查账户余额和计费状态');
      console.log('3. 如需充值，请按照平台指引完成充值操作');
      console.log('4. 确认充值成功后重新运行程序');
    }
    process.exit(1);
  }
}

main();